package com.kmzx.one.project.controller;

import com.google.gson.Gson;
import com.kmzx.one.common.exceptions.NoSuchObjectException;
import com.kmzx.one.common.exceptions.ParameterNullException;
import com.kmzx.one.project.config.data.QiNiuConfig;
import com.kmzx.one.project.net.BaseResult;
import com.kmzx.one.project.net.UserResult;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.Auth;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@RestController
@RequestMapping(value = "wlyp")
public class BaseController {

    protected final Logger logger = LoggerFactory.getLogger(getClass());


    protected Integer sorts = 1;
    protected Integer fansSorts = 0;
    protected int pageNum = 1;
    protected int real = 0;
    protected int pageSize = 10;

    @Autowired
    private RedisTemplate<String, Object> objectRedisTemplate;


    @InitBinder
    public void initBinder(WebDataBinder binder) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
    }


    public BaseResult handleException(Exception e) {
        if (e instanceof ParameterNullException) {
            BaseResult error = BaseResult.Builder.FAIL();
            error.setErrCode(402);
            error.setErrMsg(e.getMessage());
            error.setCode(402);
            error.setMsg(e.getMessage());
            return error;
        } else if (e instanceof NoSuchObjectException) {
            BaseResult error = BaseResult.Builder.FAIL();
            NoSuchObjectException noE = (NoSuchObjectException) e;
            Integer code = noE.getCode();
            if (code != null && code != 0) {
                error.setErrCode(code);
                error.setCode(code);
            } else {
                error.setCode(401);
                error.setErrCode(401);
            }
            error.setErrMsg(e.getMessage());
            error.setMsg(e.getMessage());
            return error;
        }
        BaseResult fail = BaseResult.Builder.FAIL().setData(null);
        e.printStackTrace();
        logger.error("消息:{},{}", e.getMessage(), e.getCause());
        return fail;
    }

    public UserResult handleUserException(Exception e) {
        if (e instanceof ParameterNullException) {
            UserResult error = UserResult.Builder.FAIL();
            error.setErrCode(402);
            error.setErrMsg(e.getMessage());
            return error;
        } else if (e instanceof NoSuchObjectException) {
            UserResult error = UserResult.Builder.FAIL();
            error.setErrCode(401);
            error.setErrMsg(e.getMessage());
            return error;
        }
        UserResult fail = UserResult.Builder.FAILServer().setData(null);
        e.printStackTrace();
        logger.error("消息:{},{}", e.getMessage(), e.getCause());
        return fail;
    }

    public void beforeAopRepeat(String params) {
        // 将入参作为key自增值存入redis
        ValueOperations<String, Object> value = objectRedisTemplate.opsForValue();
        Long result = value.increment(params, 1);
        // 判断返回值是否大于1，如果是则重复提交
        if (result > 1) {
            throw new NoSuchObjectException(403, "参数重复提交");
        }
        objectRedisTemplate.expire(params, 5, TimeUnit.SECONDS); // 设置过期时间5秒
    }


    @ResponseBody
    public BaseResult parentUpload(HttpServletRequest request) throws IOException {
        try {
            BaseResult success = BaseResult.Builder.SUCC();
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
            MultipartFile file = multipartRequest.getFile("file");
            logger.info("上传文件开始,fileName:{}", file.getOriginalFilename());
            String fileType = StringUtils.substringAfterLast(file.getOriginalFilename(), ".");
            String fullPath = "kmzx/" + generateFileName(fileType);
            asyncUpload(fullPath, file.getInputStream());
            success.setData(qiNiuConfig.getDomainHost() + fullPath);
            return success;
        } catch (Exception e) {
            BaseResult fail = BaseResult.Builder.FAILServer().setData(null);
            fail.setErrMsg("文件异常");
            e.printStackTrace();
            logger.error("消息:{},{}", e.getMessage(), e.getCause());
            return fail;
        }
    }


    @Autowired
    AtomicInteger atomicInteger;
    @Autowired
    QiNiuConfig qiNiuConfig;

    /**
     * 异步上传数据
     *
     * @param fileName
     * @param input
     */
    public void asyncUpload(String fileName, InputStream input) {
        Configuration cfg = new Configuration(Zone.huanan());
        UploadManager uploadManager = new UploadManager(cfg);
        String accessKey = qiNiuConfig.getAppKey();
        String secretKey = qiNiuConfig.getAppSecret();
        String bucket = qiNiuConfig.getBucketName1();
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(input, fileName, upToken, null, null);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            logger.info("请求返回的数据key:{}", putRet.key);
            logger.info("请求返回的数据Hash:{}", putRet.hash);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
            } catch (QiniuException ex2) {
            }
        }
    }

    public String generateFileName(String fileType) {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        StringBuilder sb = new StringBuilder();
        sb.append(year);
        sb.append("/");
        sb.append(calendar.get(Calendar.MONTH) + 1);
        sb.append("/");
        sb.append(calendar.get(Calendar.DAY_OF_MONTH));
        sb.append("-");
        sb.append(calendar.get(Calendar.HOUR_OF_DAY));// 1位
        sb.append(calendar.get(Calendar.MINUTE));// 1位
        sb.append(calendar.get(Calendar.SECOND));// 1位
        sb.append("-");
        sb.append(atomicInteger.getAndIncrement());
        sb.append(RandomStringUtils.randomAlphanumeric(6));
        sb.append(".");
        sb.append(fileType);
        return sb.toString();
    }
}
